use crate::models::{NewTutorial, Tutorial};
use crate::schema::tutorials::dsl::*;
use crate::utils;
use diesel::prelude::*;
use diesel::MysqlConnection;

pub fn insert(
    conn: &MysqlConnection,
    mut new_tutorial: NewTutorial,
) -> std::result::Result<usize, diesel::result::Error> {
    new_tutorial.id = utils::uuid_str();
    let result = diesel::insert_into(tutorials)
        .values(&new_tutorial)
        .execute(conn)?;
    Ok(result)
}

pub fn update(
    conn: &MysqlConnection,
    new_tutorial: NewTutorial,
) -> std::result::Result<usize, diesel::result::Error> {
    let result = diesel::update(tutorials.filter(id.eq(new_tutorial.id)))
        .set((
            pid.eq(new_tutorial.pid),
            tid.eq(new_tutorial.tid),
            title.eq(new_tutorial.title),
            rank.eq(new_tutorial.rank),
            description.eq(new_tutorial.description),
            keyword.eq(new_tutorial.keyword),
            content.eq(new_tutorial.content),
            hidden.eq(new_tutorial.hidden),
        ))
        .execute(conn)?;
    Ok(result)
}

/// 根据分类 id 获取所属 id 下所有的一级文章
pub fn get_by_tid(
    tid_str: String,
    is_get_all: bool,
    show_hidden: bool,
    conn: &MysqlConnection,
) -> std::result::Result<Vec<Tutorial>, diesel::result::Error> {
    if show_hidden {
        if is_get_all {
            tutorials
                .filter(tid.eq(tid_str))
                .order(rank.desc())
                .then_order_by(created_at.asc())
                .load::<Tutorial>(conn)
        } else {
            tutorials
                .filter(tid.eq(tid_str))
                .filter(pid.eq(""))
                .order(rank.desc())
                .then_order_by(created_at.asc())
                .load::<Tutorial>(conn)
        }
    } else {
        if is_get_all {
            tutorials
                .filter(hidden.eq(false))
                .filter(tid.eq(tid_str))
                .order(rank.desc())
                .then_order_by(created_at.asc())
                .load::<Tutorial>(conn)
        } else {
            tutorials
                .filter(hidden.eq(false))
                .filter(tid.eq(tid_str))
                .filter(pid.eq(""))
                .order(rank.desc())
                .then_order_by(created_at.asc())
                .load::<Tutorial>(conn)
        }
    }
}

/// 根据分类编号  获取该分类的 第一篇文章
pub fn get_first_by_tid(
    tid_str: String,
    show_hidden: bool,
    conn: &MysqlConnection,
) -> std::result::Result<Tutorial, diesel::result::Error> {
    if show_hidden {
        tutorials
            .filter(tid.eq(tid_str))
            .filter(pid.eq(""))
            .order(rank.desc())
            .then_order_by(created_at.asc())
            .first::<Tutorial>(conn)
    } else {
        tutorials
            .filter(hidden.eq(false))
            .filter(tid.eq(tid_str))
            .filter(pid.eq(""))
            .order(rank.desc())
            .then_order_by(created_at.asc())
            .first::<Tutorial>(conn)
    }
}

pub fn get(
    id_str: String,
    show_hidden: bool,
    conn: &MysqlConnection,
) -> std::result::Result<Tutorial, diesel::result::Error> {
    if show_hidden {
        tutorials.filter(id.eq(id_str)).first::<Tutorial>(conn)
    } else {
        tutorials
            .filter(hidden.eq(false))
            .filter(id.eq(id_str))
            .first::<Tutorial>(conn)
    }
}

pub fn get_latest(
    count: i64,
    conn: &MysqlConnection,
) -> std::result::Result<Vec<Tutorial>, diesel::result::Error> {
    tutorials
        .filter(hidden.eq(false))
        .order(created_at.desc())
        .limit(count)
        .load::<Tutorial>(conn)
}

//根据 id 获取属于该 id 的所有子个数
pub fn count_children(
    id_str: String,
    conn: &MysqlConnection,
) -> std::result::Result<i64, diesel::result::Error> {
    tutorials
        .filter(pid.eq(id_str))
        .count()
        .get_result::<i64>(conn)
}

pub fn delete(
    id_str: String,
    conn: &MysqlConnection,
) -> std::result::Result<usize, diesel::result::Error> {
    diesel::delete(tutorials)
        .filter(id.eq(id_str))
        .execute(conn)
}
